home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gawk / gawk213s.zoo / gawk-src-2.13 / io.c < prev    next >
C/C++ Source or Header  |  1991-06-19  |  19KB  |  853 lines

  1. /*
  2.  * io.c - routines for dealing with input and output and records
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. #ifndef O_RDONLY
  29. #include <fcntl.h>
  30. #endif
  31.  
  32. #ifndef atarist
  33. #define INVALID_HANDLE (-1)
  34. #else
  35. #define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
  36. #endif
  37.  
  38. static IOBUF *nextfile P((void));
  39. static int inrec P((IOBUF *iop, int getline_redirect));
  40. static int iop_close P((IOBUF *iop));
  41. struct redirect *redirect P((NODE *tree, int *errflg));
  42. static void close_one P((void));
  43. static int close_redir P((struct redirect *rp));
  44. #if (!defined(MSDOS)) && (!defined(atarist))
  45. static int wait_any P((int interesting));
  46. #endif
  47. static IOBUF *gawk_popen P((char *cmd, struct redirect *rp));
  48. static int gawk_pclose P((struct redirect *rp));
  49. static int do_pathopen P((char *file));
  50.  
  51. static struct redirect *red_head = NULL;
  52. static IOBUF *curfile = NULL;
  53.  
  54. extern int output_is_tty;
  55. extern NODE *ARGC_node;
  56. extern NODE *ARGV_node;
  57. extern NODE **fields_arr;
  58.  
  59. static IOBUF *
  60. nextfile()
  61. {
  62.     static int i = 1;
  63.     static int files = 0;
  64.     char *arg;
  65.     int fd = INVALID_HANDLE;
  66.  
  67.     if (curfile != NULL && curfile->cnt != EOF)
  68.         return curfile;
  69.     for (; i < (int) (ARGC_node->lnode->numbr); i++) {
  70.         arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
  71.         if (*arg == '\0')
  72.             continue;
  73.         if (!arg_assign(arg)) {
  74.             files++;
  75.             fd = devopen(arg, "r");
  76.             if (fd == INVALID_HANDLE)
  77.                 fatal("cannot open file `%s' for reading (%s)",
  78.                     arg, strerror(errno));
  79.                 /* NOTREACHED */
  80.             /* This is a kludge.  */
  81.             unref(FILENAME_node->var_value);
  82.             FILENAME_node->var_value =
  83.                 make_string(arg, strlen(arg));
  84.             FNR = 0;
  85.             i++;
  86.             break;
  87.         }
  88.     }
  89.     if (files == 0) {
  90.         files++;
  91.         /* no args. -- use stdin */
  92.         /* FILENAME is init'ed to "-" */
  93.         /* FNR is init'ed to 0 */
  94.         fd = 0;
  95.     }
  96.     if (fd == INVALID_HANDLE)
  97.         return NULL;
  98.     return curfile = iop_alloc(fd);
  99. }
  100.  
  101. void
  102. set_FNR()
  103. {
  104.     FNR = (int) FNR_node->var_value->numbr;
  105. }
  106.  
  107. void
  108. set_NR()
  109. {
  110.     NR = (int) NR_node->var_value->numbr;
  111. }
  112.  
  113. /*
  114.  * This reads in a record from the input file
  115.  */
  116. static int
  117. inrec(iop, getline_redirect)
  118. IOBUF *iop;
  119. int getline_redirect;
  120. {
  121.     char *begin;
  122.     register int cnt;
  123.     int retval = 0;
  124.  
  125.     cnt = get_a_record(&begin, iop, *RS);
  126.     if (cnt == EOF) {
  127.         cnt = 0;
  128.         retval = 1;
  129.     } else if (!getline_redirect) {
  130.             NR += 1;
  131.             FNR += 1;
  132.     }
  133.     set_record(begin, cnt, 1);
  134.  
  135.     return retval;
  136. }
  137.  
  138. static int
  139. iop_close(iop)
  140. IOBUF *iop;
  141. {
  142.     int ret;
  143.  
  144.     if (iop == NULL)
  145.         return 0;
  146.     errno = 0;
  147.  
  148.     /* Work around bug in UNICOS popen, but it shouldn't hurt elsewhere */
  149.     if (iop->fd < 3)
  150.         ret = 0;
  151.     else
  152.         ret = close(iop->fd);
  153.     if (ret == -1)
  154.         warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
  155.     free(iop->buf);
  156.     free(iop->secbuf);
  157.     if (iop == curfile)
  158.         curfile = NULL;    /* kludge -- gotta do better */
  159.     free((char *)iop);
  160.     return ret == -1 ? 1 : 0;
  161. }
  162.  
  163. void
  164. do_input()
  165. {
  166.     IOBUF *iop;
  167.     extern int exiting;
  168.  
  169.     while ((iop = nextfile()) != NULL) {
  170.         if (inrec(iop, 0) == 0)
  171.             while (interpret(expression_value) && inrec(iop, 0) == 0)
  172.                 ;
  173.         (void) iop_close(iop);
  174.         iop = NULL;
  175.         if (exiting)
  176.             break;
  177.     }
  178. }
  179.  
  180. /* Redirection for printf and print commands */
  181. struct redirect *
  182. redirect(tree, errflg)
  183. NODE *tree;
  184. int *errflg;
  185. {
  186.     register NODE *tmp;
  187.     register struct redirect *rp;
  188.     register char *str;
  189.     int tflag = 0;
  190.     int outflag = 0;
  191.     char *direction = "to";
  192.     char *mode;
  193.     int fd;
  194.  
  195.     switch (tree->type) {
  196.     case Node_redirect_append:
  197.         tflag = RED_APPEND;
  198.     case Node_redirect_output:
  199.         outflag = (RED_FILE|RED_WRITE);
  200.         tflag |= outflag;
  201.         break;
  202.     case Node_redirect_pipe:
  203.         tflag = (RED_PIPE|RED_WRITE);
  204.         break;
  205.     case Node_redirect_pipein:
  206.         tflag = (RED_PIPE|RED_READ);
  207.         break;
  208.     case Node_redirect_input:
  209.         tflag = (RED_FILE|RED_READ);
  210.         break;
  211.     default:
  212.         fatal ("invalid tree type %d in redirect()", tree->type);
  213.         break;
  214.     }
  215.     tmp = force_string(tree_eval(tree->subnode));
  216.     str = tmp->stptr;
  217.     for (rp = red_head; rp != NULL; rp = rp->next)
  218.         if (strlen(rp->value) == tmp->stlen
  219.             && STREQN(rp->value, str, tmp->stlen)
  220.             && ((rp->flag & ~RED_NOBUF) == tflag
  221.             || (outflag
  222.                 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
  223.             break;
  224.     if (rp == NULL) {
  225.         emalloc(rp, struct redirect *, sizeof(struct redirect),
  226.             "redirect");
  227.         emalloc(str, char *, tmp->stlen+1, "redirect");
  228.         memcpy(str, tmp->stptr, tmp->stlen);
  229.         str[tmp->stlen] = '\0';
  230.         rp->value = str;
  231.         rp->flag = tflag;
  232.         rp->fp = NULL;
  233.         rp->iop = NULL;
  234.         rp->pid = 0;    /* unlikely that we're worried about init */
  235.         rp->status = 0;
  236.         /* maintain list in most-recently-used first order */
  237.         if (red_head)
  238.             red_head->prev = rp;
  239.         rp->prev = NULL;
  240.         rp->next = red_head;
  241.         red_head = rp;
  242.     }
  243.     while (rp->fp == NULL && rp->iop == NULL) {
  244.         mode = NULL;
  245.         errno = 0;
  246.         switch (tree->type) {
  247.         case Node_redirect_output:
  248.             mode = "w";
  249.             if (rp->flag & RED_USED)
  250.                 mode = "a";
  251.             break;
  252.         case Node_redirect_append:
  253.             mode = "a";
  254.             break;
  255.         case Node_redirect_pipe:
  256.             if ((rp->fp = popen(str, "w")) == NULL)
  257.                 fatal("can't open pipe (\"%s\") for output (%s)",
  258.                     str, strerror(errno));
  259.             rp->flag |= RED_NOBUF;
  260.             break;
  261.         case Node_redirect_pipein:
  262.             direction = "from";
  263.             if (gawk_popen(str, rp) == NULL)
  264.                 fatal("can't open pipe (\"%s\") for input (%s)",
  265.                     str, strerror(errno));
  266.             break;
  267.         case Node_redirect_input:
  268.             direction = "from";
  269.             rp->iop = iop_alloc(devopen(str, "r"));
  270.             break;
  271.         default:
  272.             cant_happen();
  273.         }
  274.         if (mode != NULL) {
  275.             fd = devopen(str, mode);
  276.             if (fd > INVALID_HANDLE) {
  277.                 if (fd == fileno(stdin))
  278.                     rp->fp = stdin;
  279.                 else if (fd == fileno(stdout))
  280.                     rp->fp = stdout;
  281.                 else if (fd == fileno(stderr))
  282.                     rp->fp = stderr;
  283.                 else    
  284.                     rp->fp = fdopen(fd, mode);
  285.                 if (isatty(fd))
  286.                     rp->flag |= RED_NOBUF;
  287.             }
  288.         }
  289.         if (rp->fp == NULL && rp->iop == NULL) {
  290.             /* too many files open -- close one and try again */
  291. #ifdef atarist
  292.             if (errno == EMFILE)
  293. #else
  294.             if (errno == ENFILE || errno == EMFILE)
  295. #endif
  296.                 close_one();
  297.             else {
  298.                 /*
  299.                  * Some other reason for failure.
  300.                  *
  301.                  * On redirection of input from a file,
  302.                  * just return an error, so e.g. getline
  303.                  * can return -1.  For output to file,
  304.                  * complain. The shell will complain on
  305.                  * a bad command to a pipe.
  306.                  */
  307.                 *errflg = 1;
  308.                 if (tree->type == Node_redirect_output
  309.                     || tree->type == Node_redirect_append)
  310.                     fatal("can't redirect %s `%s' (%s)",
  311.                         direction, str, strerror(errno));
  312.                 else {
  313.                     free_temp(tmp);
  314.                     return NULL;
  315.                 }
  316.             }
  317.         }
  318.     }
  319.     free_temp(tmp);
  320.     return rp;
  321. }
  322.  
  323. static void
  324. close_one()
  325. {
  326.     register struct redirect *rp;
  327.     register struct redirect *rplast = NULL;
  328.  
  329.     /* go to end of list first, to pick up least recently used entry */
  330.     for (rp = red_head; rp != NULL; rp = rp->next)
  331.         rplast = rp;
  332.     /* now work back up through the list */
  333.     for (rp = rplast; rp != NULL; rp = rp->prev)
  334.         if (rp->fp && (rp->flag & RED_FILE)) {
  335.             rp->flag |= RED_USED;
  336.             errno = 0;
  337.             if (fclose(rp->fp))
  338.                 warning("close of \"%s\" failed (%s).",
  339.                     rp->value, strerror(errno));
  340.             rp->fp = NULL;
  341.             break;
  342.         }
  343.     if (rp == NULL)
  344.         /* surely this is the only reason ??? */
  345.         fatal("too many pipes or input files open"); 
  346. }
  347.  
  348. NODE *
  349. do_close(tree)
  350. NODE *tree;
  351. {
  352.     NODE *tmp;
  353.     register struct redirect *rp;
  354.  
  355.     tmp = force_string(tree_eval(tree->subnode));
  356.     for (rp = red_head; rp != NULL; rp = rp->next) {
  357.         if (strlen(rp->value) == tmp-